{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# FFT\n",
    "\n",
    "Code examples from [Think Complexity, 2nd edition](http://greenteapress.com/wp/complexity2), Appendix A\n",
    "\n",
    "Copyright 2017 Allen Downey, [MIT License](http://opensource.org/licenses/MIT)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from __future__ import print_function, division\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "import os\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "import thinkplot\n",
    "\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Empirical order of growth\n",
    "\n",
    "Sometimes we can figure out what order of growth a function belongs to by running it with a range of problem sizes and measuring the run time.\n",
    "\n",
    "To measure runtimes, we'll use `etime`, which uses `os.times` to compute the total time used by a process, including \"user time\" and \"system time\".  User time is time spent running your code; system time is time spent running operating system code on your behalf."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def etime():\n",
    "    \"\"\"Measures user and system time this process has used.\n",
    "\n",
    "    Returns the sum of user and system time.\"\"\"\n",
    "    user, sys, chuser, chsys, real = os.times()\n",
    "    return user+sys"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`time_func` takes a function object and a problem size, `n`, runs the function, and returns the elapsed time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def time_func(func, n):\n",
    "    \"\"\"Run a function and return the elapsed time.\n",
    "    \n",
    "    func: function\n",
    "    n: problem size\n",
    "    \n",
    "    returns: user+sys time in seconds\n",
    "    \"\"\"\n",
    "    start = etime()\n",
    "    func(n)\n",
    "    end = etime()\n",
    "    elapsed = end - start\n",
    "    return elapsed"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`run_timing_test` takes a function, runs it with a range of problem sizes, and returns two lists: problem sizes and times."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def run_timing_test(func, max_time=1):\n",
    "    \"\"\"Tests the given function with a range of values for n.\n",
    "    \n",
    "    func: function object\n",
    "\n",
    "    returns: list of ns and a list of run times.\n",
    "    \"\"\"\n",
    "    ns = []\n",
    "    ts = []\n",
    "    for i in range(6, 28):\n",
    "        n = 2**i\n",
    "        t = time_func(func, n)\n",
    "        print(n, t)\n",
    "        if t > 0:\n",
    "            ns.append(n)\n",
    "            ts.append(t)\n",
    "        if t > max_time:\n",
    "            break\n",
    "\n",
    "    return ns, ts"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`fit` takes the lists of ns and ts and fits it with a curve of the form `a * n**exp`, where `exp` is a given exponent and `a` is chosen so that the line goes through a particular point in the sequence, usually the last. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def fit(ns, ts, exp=1.0, index=-1):\n",
    "    \"\"\"Fits a curve with the given exponent.\n",
    "    \n",
    "    ns: sequence of problem sizes\n",
    "    ts: sequence of times\n",
    "    exp: exponent of the fitted curve\n",
    "    index: index of the element the fitted line should go through\n",
    "    \n",
    "    returns: sequence of fitted times\n",
    "\n",
    "    \n",
    "    \"\"\"\n",
    "    # Use the element with the given index as a reference point, \n",
    "    # and scale all other points accordingly.\n",
    "    nref = ns[index]\n",
    "    tref = ts[index]\n",
    "\n",
    "    tfit = []\n",
    "    for n in ns:\n",
    "        ratio = n / nref\n",
    "        t = ratio**exp * tref\n",
    "        tfit.append(t)\n",
    "\n",
    "    return tfit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`plot_timing_test` plots the results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def plot_timing_test(ns, ts, label='', color='blue', exp=1.0, scale='log'):\n",
    "    \"\"\"Plots data and a fitted curve.\n",
    "\n",
    "    ns: sequence of n (problem size)\n",
    "    ts: sequence of t (run time)\n",
    "    label: string label for the data curve\n",
    "    color: string color for the data curve\n",
    "    exp: exponent (slope) for the fitted curve\n",
    "    \"\"\"\n",
    "    tfit = fit(ns, ts, exp)\n",
    "    plt.plot(ns, tfit, color='0.7', linewidth=2, linestyle='dashed')\n",
    "    plt.plot(ns, ts, 's-', label=label, color=color, alpha=0.5, linewidth=3)\n",
    "    plt.xlabel('Problem size (n)')\n",
    "    plt.ylabel('Runtime (seconds)')\n",
    "    plt.xscale(scale)\n",
    "    plt.yscale(scale)\n",
    "    plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For small values of `n`, the runtime is so short that we're probably not getting an accurate measurement of just the operation we're interested in.  But as `n` increases, runtime seems to converge to a line with slope 1.  \n",
    "\n",
    "That suggests that performing append `n` times is linear, which suggests that a single append is constant time.  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### DFT\n",
    "\n",
    "Here's an implementation of DFT using outer product to construct the transform matrix, and dot product to compute the DFT."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "PI2 = 2 * np.pi\n",
    "\n",
    "def dft(xs):\n",
    "    N = len(xs)\n",
    "    ns = np.arange(N) / N\n",
    "    ks = np.arange(N)\n",
    "    args = np.outer(ks, ns)\n",
    "    M = np.exp(-1j * PI2 * args)\n",
    "    amps = M.dot(xs)\n",
    "    return amps"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here's an example comparing this implementation of DFT with `np.fft.fft`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n1QsAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fc0a11d7cf8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "xs = np.random.normal(size=128)\n",
    "spectrum1 = np.fft.fft(xs)\n",
    "plt.plot(np.abs(spectrum1))\n",
    "\n",
    "spectrum2 = dft(xs)\n",
    "plt.plot(np.abs(spectrum2))\n",
    "\n",
    "np.allclose(spectrum1, spectrum2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, let's see what the asymptotic behavior of `np.fft.fft` looks like:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64 0.0\n",
      "128 0.0\n",
      "256 0.0\n",
      "512 0.0\n",
      "1024 0.0\n",
      "2048 0.0\n",
      "4096 0.0\n",
      "8192 0.009999999999999787\n",
      "16384 0.010000000000000231\n",
      "32768 0.020000000000000018\n",
      "65536 0.03999999999999959\n",
      "131072 0.03000000000000025\n",
      "262144 0.040000000000000036\n",
      "524288 0.08000000000000007\n",
      "1048576 0.1499999999999999\n",
      "2097152 0.3200000000000003\n",
      "4194304 0.7399999999999998\n",
      "8388608 1.4799999999999995\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fc0a25d0e80>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def test_fft(n):\n",
    "    xs = np.random.normal(size=n)\n",
    "    spectrum = np.fft.fft(xs)\n",
    "\n",
    "ns, ts = run_timing_test(test_fft)\n",
    "plot_timing_test(ns, ts, 'test_fft', exp=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Up through the biggest array I can handle on my computer, it's hard to distinguish from linear.\n",
    "\n",
    "And let's see what my implementation of DFT looks like: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64 0.009999999999999787\n",
      "128 0.009999999999999787\n",
      "256 0.03000000000000025\n",
      "512 0.09999999999999964\n",
      "1024 0.4500000000000002\n",
      "2048 0.9800000000000004\n",
      "4096 2.5199999999999996\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nJgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fc0a1343f60>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def test_dft(n):\n",
    "    xs = np.random.normal(size=n)\n",
    "    spectrum = dft(xs)\n",
    "\n",
    "ns, ts = run_timing_test(test_dft)\n",
    "plot_timing_test(ns, ts, 'test_dft', exp=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's definitely much slower than `np.fft.fft`.\n",
    "\n",
    "But it looks like it's not as bad as quadratic.  Maybe it's linear?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAY4AAAEOCAYAAACetPCkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Wl0nOWV6Pv/1ixZgy3J8qRZKuyAwQMC4zgMZghDwhgC\nBOgknT4hOaeTk3XuOkkn9yYkzTnpJOv24mZON00ICRAShgDhkIEAJrgJMdjGwWZySbImD7IkW5Il\na6za98NTkspGtqpkld5S1f6t5YXqqbfe2jJlbT3jFlXFGGOMiVSK1wEYY4yZWyxxGGOMiYolDmOM\nMVGxxGGMMSYqljiMMcZExRKHMcaYqFjiMMYYExVLHMYYY6JiicMYY0xULHEYY4yJSprXAcRCcXGx\nVlZWeh2GMcbMGdu2betU1YWRXJuQiaOyspKtW7d6HYYxxswZItIc6bU2VGWMMSYqCZU4RORqEbmn\np6fH61CMMSZhJVTiUNWnVfWOgoICr0MxxpiElZBzHJMZGRmhra2NwcFBr0OJW1lZWZSWlpKenu51\nKMaYOJY0iaOtrY28vDwqKysREa/DiTuqSldXF21tbVRVVXkdjjEmQnfeCS0t720vL4e77orNeyZN\n4hgcHLSkcRIiQlFRER0dHV6HYoyJQksLVFZCMAj798PSpSACTU2xe8+kSRyAJY0p2N+PMXPTkSPw\nzjvQ3+8SSFlZbN8vqRKHMcYkkpERZe9epbk5BVXXtmcPFBfH9n0TalXVTLnzTvjkJ9/75847p3/P\n7u5ufvzjH0/rtd/97nc5evRoxNfff//9fO5znwOgo6ODdevWsWbNGjZv3sy//Mu/TCsGY0z8UFW2\nbdvPl75UT1PTwHjSSEmB6mrIyort+1vimMTYmOHxfyabgIrUbCaOcM8//zxnnnkmr7/+Oueff74l\nDmPmsGAwSFNTG3ff/TfuvruX9nYlGAwSDAaZPx/OOQdKS90cRywl5VDVN75x8ud37Jh8Yqm7e+rX\nnuj5L3/5yzQ0NLB69Wouu+wySkpKeOSRRxgaGuL666/nn//5n+nv7+emm26ira2NQCDA1772Ndrb\n29m3bx8bN26kuLiYTZs2TXr/n/3sZ3zrW99i/vz5rFq1iszMTHbs2MGXvvQlBgYG2Lp1K5dffjkD\nAwOsXr2aM844g4ceeujk34wxJi4Eg0Ha2tr4619b2LSpgJ6eHNLS0igsLKSsbB7z5qVQUADt7ROv\nKS+PXTxJmTi88O1vf5tdu3axY8cOnn32WR577DFeffVVVJVrrrmGl156iY6ODpYuXcozzzwDQE9P\nDwUFBdx9991s2rSJ4hMMXO7fv5+vf/3rbNu2jYKCAjZu3MiaNWtYvXo1d911F1u3buWHP/whAD/6\n0Y/YsWPHrH3fxphTNzg4ykMPHWDXroWkpWWwaFEh+fn5VFUJX/86LFgwu/HYUJUHnn32WZ599lnW\nrFnD2rVreeedd/D7/Zx55pn86U9/4p/+6Z/YvHkzke6A37JlCxdddBELFy4kIyODm2++OcbfgTEm\nlgKBAM3NzQSDQfbuhZ/9LIMDB3wsWrSEyspKiosL+NCHhE98YvaTBiRpj2Oq4aamJjenMVn7VK+N\nhKryla98hc985jPveW779u387ne/46tf/SqXXHIJd57KjLwxZk4ZHR2lubmZhoYGBgZGePnlLPz+\nRajCglCGqKyEa6/1JmGMScrEMZXy8snnOE5lzDAvL48jR44AcPnll/O1r32N2267jdzcXPbu3Ut6\nejqjo6MUFhZy++23M3/+fO69995jXnuioap169bxhS98ga6uLvLz83n00UdZtWrVpNemp6czMjJi\nx4oYE0dGRkZoamqisbGRkZERurqy2LFjOWlpucyb567JyIDLLoO6uthPfk/FEsckYrFNv6ioiA0b\nNrBy5UquvPJKbr31VtavXw9Abm4uDz74IPX19Xzxi18kJSWF9PR0fvKTnwBwxx13cMUVV7B06dJJ\nJ8eXLFnCN77xDdavX8/8+fNZvXr1CeO44447OOuss1i7dq1NjhsTB5qamnjnnXcYHR0lEBD27Klk\n375K8vPnjW/KjYdeRjjRsQXACUBErgaurq2t/bTf7z/mubfffpv3ve993gQ2h9jfkzGzq6WlhTfe\neINAYDHvvLOCo0cnEsZs9jJEZJuq1kVybUJNjtux6saYeDY4OMhbb73Fu+++O962eHEpw8MXsGNH\nHQMDueNJo6oK/ut/dXszvB6aOp4NVc0x69atY2ho6Ji2Bx54gDPPPNOjiIwxUxkYGKChoYGWlhaC\nwSCpqalUV1fT3p7OU0+l0NGRP35tPM1lnEhSJQ5VnfMH+W3ZsiVm906kYUtj4sHRo0epr6+nra2N\nYDAIwOLFi6mq8vHii+n85S8Q/s+uqsrNZcyf71HAEUqaxJGVlUVXVxdFRUVzPnnEwlg9jqxYH3Jj\nTJLo7+/nxRdfHP+FbMmSJfh8Pnp783n4YejsnLg2IwM++EE4++z47WWES5rEUVpaSltbm9WbOImx\nCoDGmOkZGBggOzsbgHnz5lFUVERmZia1tbVkZ+exaRPv6WVUV8M118R/LyNc0iSO9PR0q2xnjImJ\n3t5e/H4/+/fv5/zzzx8/9eHcc88lJSWFtjb4+c/ndi8jXNIkDmOMmWnd3d34/X7aQ6cLpqSk0N3d\nPZ44AoEUnnsOXnll7vcywlniMMaYKB0+fJjdu3ePD32npKRQXl5OTU3N+FBVays89VTi9DLCWeIw\nxpgojc2XpqamUlFRQXV19fjCkpER2LQp8XoZ4SxxGGPMSagqnZ2diMj4eXG1tbWkp6dTXV1NRkbG\n+LWtrfDkk9DVNfH6zEzXy1i7dm73MsJZ4jDGmEmoKgcPHsTv99Pd3U1eXh4XXHABIkJ2djYrVqwY\nv/ZEvYyaGtfLSLTDLCxxGGNMGFWlvb0dv99PT08PABkZGSxbtmx813e4lhY3l5HovYxwljiMMSak\nr6+Pbdu2jZdAyMzMpLq6moqKCtLSjv1xOTICL7wAf/1rcvQywlniMMaYkOzsbIaHh8nKyqKmpoby\n8vL39DDgxL2Myy+HNWsSs5cRzhKHMSYpBYNB2traaG5u5rzzziM9PZ3U1FTWrVvHvHnzJk0YydzL\nCGeJwxiTVAKBAG1tbdTX1zMwMABAa2sr1dXVAOTn50/6umTvZYSzxGGMSQqBQICWlhYaGhoYHBwE\nXPXN2tpali5desLXjYzA88/Dli3H9jJqa+Hqq5OnlxHOEocxJils3759/GiQvLw8fD4fS5YsOelp\n2S0tbl/GoUMTbcnaywhnicMYk5BGRkYIBALjO7rLy8sZHBzE5/OxaNGikyYM62WcnCUOY0xCGR4e\npqmpiT179lBSUsKaNWsAKCkpoaSkZMp6PM3Nbi7j+F7GFVfA6tXJ28sIF/eJQ0TmAT8GhoEXVfUh\nj0MyxsSh4eFhGhsbaWpqYnR0FHA1voPBICkpKVMmjOFh18t49dX39jKuuQZOMGeelDxJHCJyH/Bh\n4KCqrgxrvwL4HpAK3Kuq3wZuAB5T1adF5NeAJQ5jzLihoSEaGhpobm4mEAgAUFxcjM/no6io6ISv\nu/NON4cB0Nfnvh4edsNQGzdaL+NkvOpx3A/8EPjFWIOIpAI/Ai4D2oDXROS3QCmwM3RZYHbDNMbE\nu5GRERobGwE3HOXz+ViwYMGUr2tpgbIyaGx0R5/n5Lg/3d3g87m5DOtlTM6TxKGqL4lI5XHN5wL1\nqtoIICK/Aq7FJZFSYAeQcqJ7isgdwB3gJsGMMYnp6NGj7N27l9raWkSE3NxcTj/9dAoLC5kf4Znl\nwaDbj7Fvn+tljElLg/JyuPVW62WcTDzNcSwDWsMetwHrgO8DPxSRDwFPn+jFqnoPcA9AXV2dnug6\nY8zc1N/fT319PW1tbagqBQUFlJSUAIxv3puKKtTXw5/+5I5AD88zhYWwfDns329JYyrxlDgmpar9\nwN97HYcxxht9fX34/X727t073rZs2TJycnKius++fS5h7NlzbHtGhiuytGiRJYxIxVPi2AuUhT0u\nDbUZY5LUzp07aW5uBkBEKC0tpba2lnnz5kV8j+5ut1pq585j21NSoLLSzXNMciyVOYl4ShyvAT4R\nqcIljFuAW6O5gYhcDVxdW1sbg/CMMbNBVceXzmZmZiIilJWVUVtbG1UvY2AANm92m/gCYctqUlJc\nze/BQThwwA1ZhbMp0qmJ6uxPB4jIw8BFQDHQDnxdVX8qIlcB38Utx71PVb85nfvX1dXp1q1bZypc\nY8wsOHz4MH6/n+Li4vE5i5GREUZHR8nOzo74PqOjbi/G5s0ueYRbsQIuvRRCFWBNGBHZpqp1kVzr\n1aqqj52g/XfA72Y5HGOMh7q6uvD7/XR2dgJuTqOqqgoRIT09nfT09Ijuowq7drlhqe7uY58rLYXL\nLoOKipmOPjnF01CVMSZJqCpdXV3s3r2bQ6GzPdLS0qisrBxPGtHYs8dNfO/bd2x7YSFccgmcfrpN\nfM+khEocNsdhzNzQ2dnJli1bAEhPTx9PGBkZGVHd5+BBlzD8/mPbc3Lgwguhrs4mvmMhoRKHqj4N\nPF1XV/dpr2MxxkxQVY4cOTJeJKm4uJjCwkIWLlxIZWVlxMNRY3p74cUX4fXXjz1XKi0N1q+HDRsg\ndCiuiYGEShzGmPiiquzfvx+/309fXx8XX3wx2dnZiAjr16+PekhqaAhefhleecUdfT5GBFatgosv\ntmNCZoMlDmPMjAsGg+zbt4/6+nr6+voAt7S2v79/fIVUNEkjEIDt210vo7//2Odqa91KqcWLZyp6\nMxVLHMaYGdXa2orf7+fo0aMAZGdnU1NTQ1lZGalRTjiowjvvwHPPHVvrG1yiuOwyqKmZqchNpBIq\ncdjkuDHeO3DgAEePHiUnJ4fa2lpKS0tJSTnh+aQn1NoKzz773g16BQVuSOqss2yllFc82QAYa7YB\n0JjZEQgEaGlpoaCggMLCQgB6e3vp7e1l6dKl00oYXV1uL8Zbbx3bnpUF558P554LUc6lmwjE/QZA\nY8zcNjo6SktLCw0NDQwNDVFcXMx5550HQH5+/vjqqWj098Of/wxbt7pjz8ekpsI558AFF7hltsZ7\nljiMMREbHR2lqamJxsZGhkOFLPLz86moqDjmjKlojIy4VVIvv+xWTYVbudJt4IugLpOZRZY4jDER\n6ezsZNu2bYyE1sHOnz8fn89HSUnJtBJGMAh/+xu88AIcOXLscxUV8MEPwrJlMxG5mWmWOIwxJxTe\ni8jLyyMQCFBYWIjP56O4uHhaCSO8mNLBg8c+t3ChW1p72mk28R3PEipx2KoqY2bG0NAQDQ0NdHR0\ncP7555OSkkJmZiYXXXRR1AWUwu3f71ZKHV9MKTcXNm6ENWvcsecmvkWVOERkHjCoqoEpL/aAHTli\nzKkZGBigsbGR5uZmgqEZ6s7OzvESrdNNGt3dbkjqjTeObc/IcMeDrF/vvjZzw0kTh4ik4Aoq3Qac\nAwwBmSLSCTwD/Luq1sc8SmNMTB09epSGhgZaW1vHE8aiRYvw+XzMDy/MHaWTFVNauxYuusj1Nszc\nMlWPYxPwHPAVYJeqBgFEpBDYCHxHRJ5Q1QdjG6YxJlZUlS1bttAfOstjyZIl+Hy+aS2pHTM6Cq+9\nBi+9NHkxpUsucfMZZm6aKnFcqqojxzeq6iHgceBxEbGtOMbMMX19fWRkZJCRkYGIUFNTQ2dnJz6f\nj7y8vGnf92TFlJYtcyulrJjS3HfSxDGWNESkBmhT1SERuQg4C/iFqnZPlliMMfGpt7eX+vp69u3b\nR01NDe973/sAKC8vp/wUi22fqJjSggVupZQVU0ockU6OPw7UiUgtcA/wFPBL4KpYBTYdtqrKmMn1\n9PTg9/s5cOAA4E6mDYZvzz4FBw+6Qwh37z623YopJa5IE0dQVUdF5HrgB6r6AxF5PZaBTYetqjLm\nWL29vbzzzjscDG2YSElJoby8nJqamvHjzaNx553Q0uK+Hhlxy2sPHXIHD27c6NrT0uC88+ADH7Bi\nSokq0sQxIiIfAz4BXB1qs7kNY+LcyMgIBw8eJDU1lYqKCqqrq8k6hZ/mLS1QXg7NzS5pBIMwf76b\nzxgrprRxo0skJnFFmjj+Hvgs8E1V3SMiVcADsQvLGBMtVaWrq4uuri6WL18OQFFREWeeeSaLFy8m\nMzPzlN8jGISdO+Hw4WPb8/LgM5+xYkrJIqLEoapvAf897PEe4DuxCsoYEzlVpaOjA7/fz+HQT/Ql\nS5aML6etmKFlTMGg62mET3Dn5kJ1tasBbkkjeUy1AXAncMKCHap61oxHZIyJiKrS3t6O3++np6cH\ngPT0dKqrq6c1f3Hy94KnnoKeHjc0BW5ZbWWlSyS9vTP6dibOTdXj+HDov/8Y+u/Y8NTtnCShGGNi\nS1V5+eWX6Q5tlsjIyKC6uprKykrS0mb2CDpV+P3v3Um2Y0pLJ5KGST5T7eNoBhCRy1R1TdhT/yQi\n24EvxzI4Y8yEsWqdIoKIkJ+fz8DAADU1NVRUVERdzztSL7wAr77qvi4ocMeFpKa6Yasxp7gFxMwx\nkf5qIiKyQVVfDj14PxB3Z1jaPg6TiILBIHv37qW+vp7ly5ezdOlSAFasWMEZZ5wRs4QB8J//6c6a\nGvP5z8MNN9gJtsku0sTxD8B9IlIACHAY+FTMopom28dhEkkwGKS1tZWGhgaOHj0KwN69e8cTR0aM\nj5N97TW3sW/MaafB9ddb0jCRr6raBqwKJQ5UtSemURmTxAKBAK2trdTX1zM4OAjAvHnz8Pl840kj\n1t54A555ZuJxZSV89KO2A9w4ESUOEckEPgJUAmljVb9U9a6YRWZMkmptbWXXrl2Aq7pXW1vL0qVL\np1VtbzreeQeefHLi8bJl8LGPQbpt+TUhkQ5VPQX0ANtwNTmMMTNkdHSU3t5eCgsLASgrK6O9vZ3y\n8nIWL148awkDoKEBHn3U7dkAKCmB22+HGdg7aBJIpImjVFWviGkkxiSZkZER9uzZw55QHdWLL76Y\n9PR0UlNTWbdu3azH09oKv/rVRMGlwkL4+MdhhreEmAQQaeL4i4icqao7YxqNMUlgeHh4PGGMjo4C\nsGDBAoaHh0n3aDxo/3546CF3cCFAfr5LGladz0wm0sTxAeCTIrIHN1QlgNrOcWMiFwgE2L17N01N\nTQRCv9YXFRXh8/koKiqa1SGpcJ2d8OCDEJqHZ948lzROoWKsSXCRJo4rYxqFMUkgJSWFzs5OAoEA\nCxcuxOfzjc9reKW7G37xCwhVjSUrC/7u76C42NOwTJyLdDlus4isAs4PNW1W1b+d7DXGJLuBgQHq\n6+upqqoiNzcXEWHlypWAG5ry2pEjLmmMnTOVkQG33WaHFZqpRboc9wvAp4HfhJoeFJF7VPUHMYvM\nmDmqv7+f+vp62traUFUCgQCrV68G4iNhABw9Cg884IowgdufccstUFbmbVxmbohm5/g6Ve0HEJHv\nAK8AcZU47MgR46W+vj7q6+vZu3fv+LlSS5cupaamxuPIjjU05CbCQ0UBSUlxm/uqq72Ny8wdEZ9V\nBQTCHgdCbXHFjhwxXmlqahrftCcilJaWUltbS26cLUsaGYFf/hL27nWPReC662DFCm/jMnNLpInj\nZ8AWEXki9Pg64KexCcmYuSEQCIwfMFhcXExKSgqlpaXU1NQwb948j6N7r0AAHnnk2FNtP/QhOMvW\nRpooRTo5freIvIhblgvw96r6esyiMiaOdXd34/f7GRoaYsOGDYgIubm5XHrppTE/eHC6gkH4zW/A\n759ou+wyqKvzLiYzd0U6OX4e8Kaqbg89zheRdaq6JabRGRNHDh06hN/vp6OjA3DLa/v7+8eHo+I1\naajC00/Dm29OtF1wAWzY4F1MZm6LdKjqJ8DasMd9k7QZk3BUla6uLvx+P11dXQCkpqZSWVlJdXU1\nmXF+iJMq/PGP8HrY+MC6dbBxo3cxmbkv4slxHVsmAqhqUERmtj6lMXEoEAiwbds2RkZGSEtLo6qq\niqqqqrjtXRzvz3+Gv/514vHq1XDFFVby1ZyaSH/4N4rIf8f1MgD+G9AYm5CM8Y6qcvDgQYqLi0lN\nTSUtLQ2fz8fo6ChVVVWenSU1Ha+8Ai++OPH49NPhmmssaZhTF2ni+CzwfeCrgALPA3fEKihjZpuq\ncuDAAfx+P729vZxxxhlUVVUBUD0HNzhs2+aGqMbU1lrJVzNzIl1VdRC4JcaxGDPrVJV9+/ZRX1/P\nkSNHAMjMzCQtbe6OxO7aBf/n/0w8rqiAm2+GOfwtmTgT6aqq03DDVItUdaWInAVco6r/O6bRGRND\n7e3tvPXWW/SHTvjLysqitraWsrKy8f0Zc83u3W7Z7diM5JIlVr3PzLxIfwf5D+CLwL8DqOobIvJL\nwBKHmbNGR0fp7+8nJyeHmpoaysrKSJnDYzl79rgNfmPV+xYudCfdZmV5G5dJPJEmjhxVffW4egGj\nMYjHmJgIBAK0trYyPDzMaaedBjBex3vx4sVzOmEAtLXBww9DqC4UCxa4mho5Od7GZRJTpImjU0Rq\ncBPjiMiNwP6YRWXMDAkEAjQ3N9PQ0MDQ0BApKSmUl5eTlZWFiLB06VKvQzxl7e3u0MLhYfc4L88l\njbw8b+MyiSvSxPGPwD3AChHZC+wBbo9ZVNNkp+OaMaOjozQ1NdHY2Mhw6Cdqfn4+Pp8v7jftRaOr\nyx2PPjDgHufkuKQRJ6e3mwQlYfv6pr5YZB6QoqpHYhfSqaurq9OtW7d6HYbxyPDwMJs2bWIkVEC7\noKCA0047jZKSEs/Ks8ZCTw/cd5/7L0BmJnziE5AAnSjjARHZpqoRnV4WTSGnnwFHgP8QkbXAl1X1\n2emHaczMGRkZGd+cl5GRwYIFCxgZGcHn87Fw4cKEShgAfX2uet9Y0khPd9X7LGmY2RDpUNWnVPV7\nInI5UAT8HfAAYInDeGpoaIjGxkaamppYt27deA3vtWvXkpqamnAJA9yw1AMPuGEqcNX7br4Zysu9\njcskj2gKOQFcBfxCVd+URPwXaeaMwcFBGhoaaG5uJhhaf9rR0TGeOObyBr6TGR52E+Ht7e6xCHzk\nI25nuDGzJdJ/XdtE5FmgCviKiOQBwdiFZczkBgYGqK+vp7W1dTxhlJSU4PP54qaed6yMjrolt21t\nE23XXuvOoDJmNkVTc3w10KiqR0WkCPj72IVlzOT27NlDc6iE3eLFi/H5fBQUFHgcVewFAvDoo26T\n35irrnKn3Roz206aOESkUlWbVDUIbB9rV9UuoCs0XLVMVdtOeBNjTkFfXx9DQ0MUFRUBUFNTw9DQ\nEDU1NeTn53sc3exQhSefhHffnWi75BI491zvYjLJbaoex/8rIinAU8A2oAPIAmqBjcAlwNcBSxxm\nRh05cgS/38++ffvIycnhoosuIiUlhczMTNasWeN1eLNGFZ55BnbunGj7wAfcH2O8ctLEoaofFZHT\ngduATwFLgKPA28DvgG+q6mDMozRJo7e3F7/fz/797mACEaGoqIhAIDDnjwWJlio89xyEb0k65xzX\n27ClKcZLU85xqOpbwP8zC7GYJDY0NMQbb7xBe2i5UEpKCmVlZdTU1JCTpAcubd4ML7888fiss9y8\nhiUN47XEXLNo5pz09HR6e3tJSUmhoqKC6upqsrOzvQ7LM1u2wAsvTDxesQKuu86ShokPljjMrFNV\nurq6aGxsZNWqVWRmZpKSksLatWvJyclJqLOkpmPHDvj97yceV1fDjTda9T4TPyxxmFmjqnR2duL3\n+zl06BAATU1NLF++HCDh92FE4q234KmnJh6XlcEtt1j1PhNfIj2rSnAT5NWqepeIlAOLVfXVmEZn\nEoKqcvDgQfx+P93d3YAbmqqqqhqv622gvh4ef3yiet/ixe78qYwMb+My5niR/h7zY9xO8YuBu3CH\nHT4OnBOjuEwC2bVr1/imvYyMDKqrq6moqBg/lNBAczP8+tduox9AcbFV7zPxK9LEsU5V14rI6wCq\nelhE7PcgMylVZWRkhIzQr8pLlizhwIED1NTUUF5enrDnSE3Xvn3wy19C6BR45s93SWPePG/jMuZE\nIv0XPCIiqUxUAFyInVVljhMMBtm3bx9+v5+8vDzq6tzR/kVFRVx88cWkpqZ6HGH86eiABx+EoSH3\nODfXFWJKglNUzBwWaeL4PvAEUCIi3wRuBL4as6jMnBIMBmlra6O+vp6jR48CrtcxOjpKWloaImJJ\nYxKHD7uaGqG/MrKzXdIIHfBrTNyKKHGo6kMisg13xIgA16nq2zGNzMS9QCBAa2srDQ0NDIRql+bk\n5ODz+Vi2bFnS7fSORm8v/PzncCRUSzMjA26/HUpKvI3LmEhEM9jcDmwOvSZbRNaq6vYpXmMS2PDw\nMG+++SaqSm5uLrW1tSxdutQSxhT6+10hptACM9LS4NZbYdkyb+MyJlKRLsf9X8AngQZC8xyh/14c\nm7COee9q3JEnBap6Y6zfz5zY6Ogoe/fupby8HBEhOzub5cuXk5OTw5IlSxKy2t5MGxx0cxodHe5x\nSoqr3ldZ6WlYxkQl0h7HTUCNqg5Hc3MRuQ/4MHBQVVeGtV8BfA9IBe5V1W+f6B6q2gj8g4g8Fs17\nm5kzMjJCU1MTjY2N46ullixZAkCtlZ6b0p13QkuLW2rb2Oh6HOAmwH/8Y/D5vI3PmGhFmjh2AfOB\ng1He/37gh8AvxhpCq7N+BFyGO479NRH5LS6JfOu4139KVaN9TzNDhoeH2bNnD01NTYyE1oouWLAg\n6Y8EiVZLi9sBvmsXpKe75bYAeXlwxhnexmbMdESaOL4FvC4iu4ChsUZVveZkL1LVl0Sk8rjmc4H6\nUE8CEfkVcK2qfgvXOzFxoKGhAb/fz+joKACFhYWcdtppFBUV2ZBUlEZG3PlTYxPh4GqEh/5qjZlz\nIk0cPwe+A+zk1PdvLANawx63AetOdHGoTO03gTUi8pVQgpnsujuAOwDKy8tPMUQDbk6juLgYn883\nXoHPRKe9HXbvPnYzX2UllJZCU5NXURlzaiJNHEdV9fsxjeQEQmVqPxvBdfcA9wDU1dXpFJebMAMD\nAzQ0NJAP/13gAAAU3ElEQVSdnU1NTQ0AFRUVFBYW2sGDp8Dvd3XCx3aEg5vPsNVTZq6LNHFsFpFv\nAb/l2KGq6SzH3QuUhT0uDbWZWXb06FHq6+tpa2sjGAySkZFBZWUlqamppKWlWdI4BVu2wB/+MHFg\nYWoqnH46WMfNJIJIE8dYkefzwtqmuxz3NcAnIlW4hHELcOs07mOmqb+/fzxhaOgn25IlS/D5fLbD\n+xQFgy5hvBp2bnRJCSxY4OY4wuc5bETVzFWR7hzfOJ2bi8jDwEVAsYi0AV9X1Z+KyOeAP+JWUt2n\nqm9O5/6TvN/VwNW2RPTEenp62Lx58/jjZcuWUVtbS15enodRJYahITc0VV8/0VZaCr/5jTuDyphE\nIWO/cU76pMjtqvqgiPxfkz2vqnfHLLJTUFdXp1u3bvU6jLgxMDAwXoZVVXn55ZfJy8ujtraWeXYE\n64zo7nYn3B4MWzx+xhmu3KudHm/mAhHZpqp1kVw7VY9j7KfKZL+O2gR0nOvu7sbv93Pw4EEuvPBC\ncnNzERHe//7327EgM6itDR5+eGJjH8AFF8DGjVYj3CSmkyYOVf330JfPqerL4c+JyIaYRWVOyeHD\nh9m9ezcdoXMtUlJS6OnpITc0XmJJY+bs2gVPPjmxJyM1Fa65Blat8jYuY2Ip0snxHwBrI2jzVLLP\ncXR1deH3++ns7AQgNTWViooKqqurybJScjNKFV56CTZtmmjLyXHnTlVUeBeXMbPhpIlDRNYD7wcW\nHjfPkY+b2I4rqvo08HRdXd2nvY7FC83NzXR2dpKWlkZlZSXV1dXjVfjMzBkdhd/+Ft54Y6KtuNid\ncGu1NEwymKrHkQHkhq4Ln+foxRVzMh5RVQ4ePEh6ejqFoZ9WPp+P3NxcKisrLWHESH+/qw3e0jLR\nVlUFN93kCjEZkwymmuP4M/BnEblfVZtnKSZzEqpKe3s7fr+fnp4eFixYwPvf/35EhLy8PFtWG0Od\nnfDQQ65y35izz4arrnJzG8Yki0jnODJF5B6gMvw1qhrzehzGUVX279+P3+/nSGgXWWZmJosXL/Y4\nsuTQ2AiPPOLqaYBbLXXZZbB+va2cMskn0sTxKPBvwL1AIHbhnJpEnRzv7e1l+/bt9PX1AZCVlUVN\nTQ3l5eW203sWbNsGzzzjdoWD25fxkY/AihXexmWMVyJNHKOq+pOYRjIDEnVyPDs7m8HBQbKzs6mt\nraW0tNQSxiwIBuG55+Avf5loy8tzk+ChOlbGJKVIE8fTIvLfgCc49pDDQzGJKokFAgHa2tpoa2vj\nvPPOIzU1lfT0dNavX09eXp7twZglw8Pw+OPw7rsTbUuWwMc+Bvn53sVlTDyINHF8IvTfL4a1KVA9\ns+Ekr0AgQEtLCw0NDQyGBtL37dtHWZk7SLigoMDL8JJKb687PuTAgYm2FSvghhvAFqsZE/khh1Wx\nDiRZjY6O0tzcTGNjI0NDrjOXl5eHz+cbr+ttZs++fe74kPBTbDdsgEsvtUlwY8ZElDhE5OOTtavq\nLyZr98pcnBx/9dVXOXTIjfgVFBTg8/lYtGiRlWf1wDvvuOGpscJLKSnw4Q/D2rg6H8EY70U6VHVO\n2NdZwCXAdiCuEsdcmBwfHh4GGN+gV15eTjAYxOfzUVJSYgnDA6puAvy55yYKL2VluU191TYYa8x7\nRDpU9fnwxyIyH/hVTCJKUMPDwzQ2NtLU1ERpaSkrV64EXD2MZcuWWcLwSCDgltpuD6tlWVjoVk4V\nF3sXlzHxLNIex/H6AZv3iMDg4CCNjY00NzcTCLgtMAMDA6gqImIJw0MDA25T3549E23l5XDLLe7A\nQmPM5CKd43iaifobKcDpuE2B5gQGBwepr6+npaWFYGjnWElJCT6fz2p5x4FDh9zxIV1dE22rVsHV\nV0PadH+dMiZJRPpP5F/Dvh4FmlW1LQbxJIzBwUGampoAWLRoET6fj/nz53sblAGguRl+9SvX4xhz\n8cVw/vm2csqYSEQ6x/Hn8McikiIit6nqQ7EJa+7p7+/nwIED1NTUADB//nxWrFhBSUkJ+bZjLG78\n7W/uSPTQqCFpaXD99a7MqzEmMlPV48gH/hFYBvwW+FPo8f8E/gbEVeLwYjluX18ffr+fvXv3AlBY\nWDg+FDWXlgUnOlV44QXYvHmibd48txO8tNS7uIyZi6bqcTwAHAZeAf4L8H8DAlynqjtiHFvUZnM5\nbm9vL36/n/379wMgIpSWlpKZmRnrtzZRGhmBJ56At96aaCspcSunbPTQmOhNlTiqVfVMABG5F9gP\nlKvqYMwji1Oqyo4dO8Z7GCJCWVkZtbW15NhSnLjT1+d2gof+dwHg88GNN4LleGOmZ6rEMTL2haoG\nRKQtWZNG+PLZzMxMUlJSKC8vp6amhmwr/RaX2tvdmVM9PRNt69bB5Ze7XeHGmOmZKnGsEpHe0NcC\nZIceC6CqmvCzvl1dXfj9fpYtWzZ+4GBtbS3V1dVkZWV5HJ05Eb8fHn3UnXILbrXUlVfCued6G5cx\niWCq0rFJWfRBVenq6mL37t3j50iNjIyMJw6r5x3ftmyBP/xh4viQzEw3NOXzeRuXMYnCtjqFUVU6\nOjrw+/0cDhWWTk9Pp7Kykqoq2ygf74JBlzBefXWiraAAbrvNTYYbY2aGJY4w+/fvZ3vo0KL09HSq\nq6uprKwkPT3d48jMVAYH4bHHoL5+oq201B0fkpvrXVzGJKKEShynuo9j0aJFFBQUsHTpUioqKkiz\nsyfmhO5uNwl+8OBE2xlnwHXXufrgxpiZJTo2EJxA6urqdOvWrdN67djqKTM3tLW55bb9/RNtF1wA\nGzfa8SHGRENEtqlqXSTX2q/Ux7GkMXfs2gVPPgmjo+5xaipcc407rNAYEzuWOMycowovvQSbNk20\n5eTAzTdDRYV3cRmTLCxxmDlldNQdUvjGGxNtxcXu+JDCQu/iMiaZWOIwc0Z/P/z619DSMtFWXQ0f\n/SjY5n1jZo8lDjMndHS4lVOh7TUAnH02XHWVm9swxsweSxwmLt1550TP4sgRaGpyNTQKClzRpcsu\ng/XrbeWUMV6wxGHiUkuLm+jev9+Vec3Lc+09PW4SfMUKb+MzJplZ4jBxKRiEd9+FAwcm2jIy3HlT\nljSM8VZCHS4tIleLyD094edomznn0CF3um140sjNdXMaVvLEGO8lVOJQ1adV9Y6CggKvQzHT9O67\ncM89MDAw0bZoEaxZY4WXjIkXNlRl4kIw6Db0hdcEF3FDU0uW2CS4MfHEEofxXH8/PP44NDZOtJWU\nuBVUw8PQ3DzRXl4++/EZY45licN4qq0NHnkEensn2mpq4EtfsvkMY+KVJQ7jCVV47TX44x/d/owx\nF17o/lhNcGPilyUOM+uGh+Hpp2Hnzom27Gy44QYr72rMXGCJw8yqzk533lRHx0Tb0qVw000wf753\ncRljImeJw8yat95y9TOGhyfazj4brrwSrNiiMXOH/XM1MRcIwHPPwSuvTLSlpcGHPwyrV3sXlzFm\neixxmJg6cgQeffTYo9ALC93Q1OLF3sVljJk+SxwmZpqa4LHHoK9vom35crj+esjK8iwsY8wpssRh\nZpyqG5Z67jm3Ixzczu9LLoENG2wXuDFznSUOM6MGB+Gpp+Dttyfa5s2DG2+Eqirv4jLGzJyEShwi\ncjVwdW1trdehJKX2drcLvKtroq2szJV2zc/3Li5jzMxKqP25djqud954A+6999iksW4dfPKTljSM\nSTQJ1eMws2901B0b8tprE20ZGXDNNbBypXdxGWNixxKHmbaeHjc0tXfvRFtxsSvtunChd3EZY2LL\nEoeZloYGdxT60aMTbWec4XoaVnDJmMRmicNERdUVW9q0yX0N7iTbD37QzWnYUltjEp8lDhOxgQH4\nzW9cPfAxeXlu1ZQVWDImeVjiMBHZv9+datvdPdFWWen2Z+TmehaWMcYDljjMlLZvh9/9zq2gGvOB\nD8DFF1vBJWOSkSUOc0IjIy5hvP76RFtmpjtrasUK7+IyxnjLEoeZ1OHDbmjqwIGJtkWL3Km2RUXe\nxWWM8Z4lDvMe774LTzzhzp0as2qVq5+Rnu5dXMaY+GCJw4wLBt0y282bJ9pSU12FvrPPtqW2xhjH\nEocBoL/fbehrbJxoKyhwQ1PLlnkXlzEm/ljiMLS1uaNDensn2mpq4CMfgZwc7+IyxsQnSxxJTNUd\nTvjHP7q64GMuvND9saW2xpjJWOJIUsPD8PTTsHPnRFt2NtxwA/h83sVljIl/ljiSUGenG5o6eHCi\nbelSN58xf753cRlj5gZLHEnmrbdcadehoYm2s892K6fS7NNgjImA/ahIEoEAPP88/OUvE21paW5v\nxurV3sVljJl7LHEkgSNH4LHHoLl5oq2w0A1NLV7sXVzGmLkp7hOHiFwHfAjIB36qqs96HNKc0twM\njz4KfX0TbcuXu/OmsrK8i8sYM3fFNHGIyH3Ah4GDqroyrP0K4HtAKnCvqn77RPdQ1SeBJ0VkAfCv\nwIwnjjvvhJaW97aXl8Ndd830u8XW2PeiCh0dsG+fay8ocKfZXnIJbNhgu8CNMdMX6x7H/cAPgV+M\nNYhIKvAj4DKgDXhNRH6LSyLfOu71n1LVsbU/Xw29bsa1tMCCBceWQQV3Kmz4ybBzweuvuxVSXV3u\n+xlbJdXXBx//OFRVeRufMWbui2niUNWXRKTyuOZzgXpVbQQQkV8B16rqt3C9k2OIiADfBn6vqttj\nFWt7+8Rv52O6u90KpLmktdXNaYTLz3fJxJKGMWYmeLE3eBnQGva4LdR2Ip8HLgVuFJHPnugiEblD\nRLaKyNaOjo6ZiTQBLFvmVk1lZHgdiTEmUcT95Liqfh/4fgTX3QPcA1BXV6fRvk9+vjsdNlxKCqxZ\nE+2dvPXSS1BS4uYwFi50q6eMMWYmeZE49gJlYY9LQ22eWrz4vUtTs7Lg2mu9iWe6nnjC1QI3xphY\n8SJxvAb4RKQKlzBuAW71II5x5eXQ1DR5+1yTSN+LMSY+iWrUozqR31zkYeAioBhoB76uqj8VkauA\n7+JWUt2nqt+cofe7Gri6trb2036/fyZuaYwxSUFEtqlqXUTXxjJxeKWurk63bt3qdRjGGDNnRJM4\nrOKCMcaYqFjiMMYYE5WEShwicrWI3NPT0+N1KMYYk7ASKnGo6tOqekdBQYHXoRhjTMJKyMlxEekA\nmqe8EAqASLsnkV4byXVTXVMMdEYYVzyL5u833t/3VO853dd78RlNls8nePMZjdV7nup9faoa2W/d\nqpq0f4B7ZvraSK6b6hpgq9d/N7P99xvv73uq95zu6734jCbL53Mm/r/G03vO5mc0oYaqpuHpGFwb\nyXXRvO9c5tX3GYv3PdV7Tvf1XnxGk+XzCd58r7F6z1n7jCbkUNVcJyJbNcL11MbMNvt8mmTvccSr\ne7wOwJiTsM9nkrMehzHGmKhYj8MYY0xULHEYY4yJiiUOY4wxUYn7CoDJTkSuAz4E5AM/VdVnPQ7J\nmGOIyPuAL+A2Bj6vqj/xOCQTY9bj8ICI3CciB0Vk13HtV4jIuyJSLyJfBlDVJ1X108BngZu9iNck\nnyg/o2+r6meBm4ANXsRrZpclDm/cD1wR3iAiqcCPgCuB04GPicjpYZd8NfS8MbPhfqL4jIrINcAz\nwO9mN0zjBUscHlDVl4BDxzWfC9SraqOqDgO/Aq4V5zvA71V1+2zHapJTNJ/R0PW/VdUrgdtmN1Lj\nBZvjiB/LgNawx23AOuDzwKVAgYjUquq/eRGcMZzgMyoiFwE3AJlYjyMpWOKIc6r6feD7XsdhzImo\n6ovAix6HYWaRDVXFj71AWdjj0lCbMfHCPqMGsMQRT14DfCJSJSIZwC3Abz2OyZhw9hk1gCUOT4jI\nw8ArwHIRaRORf1DVUeBzwB+Bt4FHVPVNL+M0ycs+o+Zk7JBDY4wxUbEehzHGmKhY4jDGGBMVSxzG\nGGOiYonDGGNMVCxxGGOMiYolDmOMMVGxxGESjogERGSHiOwSkUdFJCfK1/edoP1+EblxZqKcMoa7\nROTSGbjPdSJy5xTXLBSRP5zqe5nkYYnDJKIBVV2tqiuBYVwtk3GhE4fj+rOvqneq6nMzcKsvAT+e\n4r06gP0iYrU0TETi+h+PMTNgM1ArIpWhAkS/AHYBZSLyMRHZGeqZfCf8RSLy/4nImyLyvIgsPP6m\nInK2iPxZRLaJyB9FZEmo/cXQa7eKyNsico6I/EZE/CLyvye5T2qoJ7MrFMv/CLXfLyI3ikhdqPe0\nI/S8hp6vEZE/hN5/s4ismOTepwFDqtoZds/vi8hfRKTxuN7Tk9iR6CZCljhMwhKRNFzRoZ2hJh/w\nY1U9AxgBvgNcDKwGzgmV6QWYB2wNXfdn4OvH3Tcd+AFwo6qeDdwHfDPskmFVrQP+DXgK+EdgJfBJ\nESk6LszVwDJVXamqZwI/C39SVbeGek+rgT8A/xp66h7g86H3/59M3qvYABxfw2UJ8AHgw8C3w9q3\nAudPcg9j3sOOVTeJKFtEdoS+3gz8FFgKNKvqX0Pt5wAvhoZpEJGHgAtwv3kHgV+HrnsQ+M1x91+O\nSwR/EhGAVGB/2PNjB//tBN5U1f2h92jEnS7bFXZtI1AtIj/AVdCbtKa8iNwMrAU+KCK5wPuBR0Pv\nD64WxvGWAB3HtT2pqkHgLRFZFNZ+EPd3ZMyULHGYRDQQ+g19XOgHbP8073f8gW6CSwjrT3D9UOi/\nwbCvxx4f829OVQ+LyCrgctxczE3Ap455M5GVwDeAC1Q1EJqf6T7+e5zEAFBwgtjGvo8xWaHrjZmS\nDVWZZPUqcKGIFIdqaX8MNywF7t/F2Pj/rcB/Hvfad4GFIrIe3NCViJwxnSBEpBhIUdXHcXXl1x73\n/HzgYeDjY70jVe0F9ojIR0PXSCj5HO9toDbCUE7Dzf0YMyVLHCYphYaPvgxsAv4GbFPVp0JP9wPn\nisgu3BzIXce9dhiXWL4jIn8DduCGjqZjGfBiaGjtQeArxz1/LVAB/MfYJHmo/TbgH0Lv/2bouuO9\nBKyRsPGsk9iIGyozZkp2rLoxCUxEvgc8PdXSXhF5CbhWVQ/PTmRmLrMehzGJ7V+Ak26ADC03vtuS\nhomU9TiMMcZExXocxhhjomKJwxhjTFQscRhjjImKJQ5jjDFRscRhjDEmKpY4jDHGROX/B+uq/GQk\nN767AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fc0a1349b00>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_timing_test(ns, ts, 'test_dft', exp=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "No, it looks steeper than linear.  Just based on this data, we would have a hard time classifying this algorithm."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Implementing FFT\n",
    "\n",
    "Ok, let's try our own implementation of FFT.\n",
    "\n",
    "First I'll get the divide and conquer part of the algorithm working:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def fft_norec(ys):\n",
    "    N = len(ys)\n",
    "    He = dft(ys[::2])\n",
    "    Ho = dft(ys[1::2])\n",
    "    \n",
    "    ns = np.arange(N)\n",
    "    W = np.exp(-1j * PI2 * ns / N)\n",
    "    \n",
    "    return np.tile(He, 2) + W * np.tile(Ho, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This version breaks the array in half, uses `dft` to compute the DFTs of the halves, and then uses the D-L lemma to stich the results back up.\n",
    "\n",
    "Let's see what the performance looks like."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64 0.0\n",
      "128 0.009999999999999787\n",
      "256 0.019999999999999574\n",
      "512 0.08000000000000007\n",
      "1024 0.27999999999999936\n",
      "2048 1.1300000000000008\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fc0a1349748>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def test_fft_norec(n):\n",
    "    xs = np.random.normal(size=n)\n",
    "    spectrum = fft_norec(xs)\n",
    "\n",
    "ns, ts = run_timing_test(test_fft_norec)\n",
    "plot_timing_test(ns, ts, 'test_fft_norec', exp=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Looks about the same as DFT.  Again, it seems better than quadratic, but not as good as linear."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n2rQ5Qz0tAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fc0a1204dd8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_timing_test(ns, ts, 'test_fft_norec', exp=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Exercise:**  Starting with fft_norec, write a function called fft_rec that's fully recursive; that is, instead of using `dft` to compute the DFTs of the halves, it should use `fft_rec`.  Of course, you will need a base case to avoid an infinite recursion.  You have two options:\n",
    "\n",
    "1) The DFT of an array with length 1 is the array itself.\n",
    "\n",
    "2) If the parameter, `ys`, is smaller than some threshold length, you could use DFT.\n",
    "\n",
    "Use `test_fft_rec`, below, to check the performance of your function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Solution\n",
    "\n",
    "def fft_rec(ys):\n",
    "    N = len(ys)\n",
    "    if N == 1:\n",
    "        return ys\n",
    "    \n",
    "    He = fft_rec(ys[::2])\n",
    "    Ho = fft_rec(ys[1::2])\n",
    "    \n",
    "    ns = np.arange(N)\n",
    "    W = np.exp(-1j * PI2 * ns / N)\n",
    "    \n",
    "    return np.tile(He, 2) + W * np.tile(Ho, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xs = np.random.normal(size=128)\n",
    "spectrum1 = np.fft.fft(xs)\n",
    "\n",
    "spectrum2 = fft_rec(xs)\n",
    "\n",
    "np.allclose(spectrum1, spectrum2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64 0.010000000000001563\n",
      "128 0.009999999999999787\n",
      "256 0.02999999999999936\n",
      "512 0.049999999999998934\n",
      "1024 0.0600000000000005\n",
      "2048 0.08999999999999986\n",
      "4096 0.15000000000000213\n",
      "8192 0.3299999999999983\n",
      "16384 0.6099999999999994\n",
      "32768 1.240000000000002\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fc0a10941d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def test_fft_rec(n):\n",
    "    xs = np.random.normal(size=n)\n",
    "    spectrum = fft_rec(xs)\n",
    "\n",
    "ns, ts = run_timing_test(test_fft_rec)\n",
    "plot_timing_test(ns, ts, 'test_fft_rec', exp=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If things go according to plan, your FFT implementation should be faster than `dft` and `fft_norec`, but probably not as fast as `np.fft.fft`.  And it will probably be a bit steeper than linear."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
